/****************************************
*  This file created using "Writer B"   *
*      a program written by CTonk       *
*          ctonk87@hotmail.com          *
*     [timestamp 03/04/06  18:23:07]    *
****************************************/

// Character.cpp

#include "definitions.h"
#include <list>
#include "character.h"
#include "stringutil.h"
#include "timestamp.h"
#include "logs.h"
#include "board.h"
#include "note.h"
#include "world.h"

// Constructors...
Character::Character() {
	_id = 0;
	_disconnected = false;
	_socket = new Socket;
	_gotInput = false;
	_status = LOGIN;
	_vedit = false;
	//_loginHandler = 0;
	_area = 0;
	_mob = 0;
	_object = 0;
	_note = 0;
	_board = 0;
	_connection = 0;
	_prompt << "{x[{G%h{x/{g%H {C%m{x/{c%M {B%v{x/{b%V{x]";
	_pword = new char[20];
	for ( int x=0; x < 20; x++ )
		_pword[x] = '\0';
	_lname = new char[13];
	for ( int x=0; x < 13; x++ )
		_lname[x] = '\0';
	_prof = new char[20];
	for ( int x=0; x < 20; x++ )
		_prof[x] = '\0';
	_clan = new char[20];
	for ( int x=0; x < 20; x++ )
		_clan[x] = '\0';
	_bankgold = 0;
	_banksilver = 0;
	_mobdeaths = 0;
	_mobkills = 0;
	_pkdeaths = 0;
	_pkkills = 0;
	_exp = 0;
	_tnl = 0;
	_pracs = 0;
	_trains = 0;
	_gains = 0;
	_on = false;
	_title = new char[80];
	for ( int x=0; x < 80; x++ )
		_title[x] = '\0';
	_eyedesc = new char[20];
	for ( int x=0; x < 20; x++ )
		_eyedesc[x] = '\0';
	_eyecolor = new char[20];
	for ( int x=0; x < 20; x++ )
		_eyecolor[x] = '\0';
	_hairdesc = new char[20];
	for ( int x=0; x < 20; x++ )
		_hairdesc[x] = '\0';
	_haircolor = new char[20];
	for ( int x=0; x < 20; x++ )
		_haircolor[x] = '\0';
	_cheight = new char[20];
	for ( int x=0; x < 20; x++ )
		_cheight[x] = '\0';
	_cweight = new char[20];
	for ( int x=0; x < 20; x++ )
		_cweight[x] = '\0';
	_hand = 0;
	_house = new char[28];
	for ( int x=0; x < 28; x++ )
		_house[x] = '\0';
	_points = 0;
	_echocolor = 'x';
}

Character::Character( Character& it ) {
	_id = it._id;
	_connection = it._connection;
	_area = it._area;
	_mob = it._mob;
	_object = it._object;
	setNote( it.getNote() );
	setBoard( it.getBoard() );
	_vedit = it._vedit;
	for ( int x=0; x < 20; x++ )
		_pword[x] = it._pword[x];
	for ( int x=0; x < 13; x++ )
		_lname[x] = it._lname[x];
	for ( int x=0; x < 20; x++ )
		_prof[x] = it._prof[x];
	for ( int x=0; x < 20; x++ )
		_clan[x] = it._clan[x];
	_bankgold = it._bankgold;
	_banksilver = it._banksilver;
	_mobdeaths = it._mobdeaths;
	_mobkills = it._mobkills;
	_pkdeaths = it._pkdeaths;
	_pkkills = it._pkkills;
	_exp = it._exp;
	_tnl = it._tnl;
	_pracs = it._pracs;
	_trains = it._trains;
	_gains = it._gains;
	_on = it._on;
	for ( int x=0; x < 80; x++ )
		_title[x] = it._title[x];
	for ( int x=0; x < 20; x++ )
		_eyedesc[x] = it._eyedesc[x];
	for ( int x=0; x < 20; x++ )
		_eyecolor[x] = it._eyecolor[x];
	for ( int x=0; x < 20; x++ )
		_hairdesc[x] = it._hairdesc[x];
	for ( int x=0; x < 20; x++ )
		_haircolor[x] = it._haircolor[x];
	for ( int x=0; x < 20; x++ )
		_cheight[x] = it._cheight[x];
	for ( int x=0; x < 20; x++ )
		_cweight[x] = it._cweight[x];
	_hand = it._hand;
	for ( int x=0; x < 28; x++ )
		_house[x] = it._house[x];
	_points = it._points;
	_echocolor = it._echocolor;
}

// Operators...
Character& Character::operator = ( Character& it ) {
	_id = it._id;
	_connection = it._connection;
	_area = it._area;
	_mob = it._mob;
	_object = it._object;
	setNote( it.getNote() );
	setBoard( it.getBoard() );
	_vedit = it._vedit;
	for ( int x=0; x < 20; x++ )
		_pword[x] = it._pword[x];
	for ( int x=0; x < 13; x++ )
		_lname[x] = it._lname[x];
	for ( int x=0; x < 20; x++ )
		_prof[x] = it._prof[x];
	for ( int x=0; x < 20; x++ )
		_clan[x] = it._clan[x];
	_bankgold = it._bankgold;
	_banksilver = it._banksilver;
	_mobdeaths = it._mobdeaths;
	_mobkills = it._mobkills;
	_pkdeaths = it._pkdeaths;
	_pkkills = it._pkkills;
	_exp = it._exp;
	_tnl = it._tnl;
	_pracs = it._pracs;
	_trains = it._trains;
	_gains = it._gains;
	_on = it._on;
	for ( int x=0; x < 80; x++ )
		_title[x] = it._title[x];
	for ( int x=0; x < 20; x++ )
		_eyedesc[x] = it._eyedesc[x];
	for ( int x=0; x < 20; x++ )
		_eyecolor[x] = it._eyecolor[x];
	for ( int x=0; x < 20; x++ )
		_hairdesc[x] = it._hairdesc[x];
	for ( int x=0; x < 20; x++ )
		_haircolor[x] = it._haircolor[x];
	for ( int x=0; x < 20; x++ )
		_cheight[x] = it._cheight[x];
	for ( int x=0; x < 20; x++ )
		_cweight[x] = it._cweight[x];
	_hand = it._hand;
	for ( int x=0; x < 28; x++ )
		_house[x] = it._house[x];
	_points = it._points;
	_echocolor = it._echocolor;
	return (*this);
}

// get rid of the socket when Character is deleted
// disconnect, remove from list, and delete
Character::~Character() {
	if ( _socket ) {
		if ( !_socket->GetSocketIP().empty() ) {
			SocketServer::Instance()._socketList.remove( _socket );
			SocketServer::Instance().KillSocket( _socket ); 
			if ( 1 ) {
				cout << _socket->GetSocketIP() << " has disconnected @ " << Timestamp::Instance().GetDateTime() << "\n\r";
			} else {
				cout << "name" << " has disconnected @ " << Timestamp::Instance().GetDateTime() << "\n\r";
			}
		}
		delete _socket;
	}
	// Also...
	_area = 0;
	_mob = 0;
	_object = 0;
	_board = 0;
	_note = 0;
	delete[] _pword;
	delete[] _lname;
	delete[] _prof;
	delete[] _clan;
	delete[] _title;
	delete[] _eyedesc;
	delete[] _eyecolor;
	delete[] _hairdesc;
	delete[] _haircolor;
	delete[] _cheight;
	delete[] _cweight;
	delete[] _house;
}

void Character::setRoom( int number ) {
	_room = World::Instance().FindRoom( number );
	if ( _status == REDIT && !_room->getArea()->getPermission( _id ) )
		// Make sure they can't enter redit mode, and then switch to a room
		// they don't have permissions to.
		_status = CONNECTED;
	return;
}

bool Character::getVEdit() {
	return _vedit;
}

void Character::setVEdit( bool vedit ) {
	_vedit = vedit;
}

void Character::setReply( std::string& reply ) {
	this->_reply = reply;
	return;
}

std::string& Character::getReply() {
	return this->_reply;
}

void Character::setRepeat( std::string repeat ) {
	this->_repeat = repeat;
	return;
}

std::string Character::getRepeat() {
	return _repeat;
}

void Character::setPrompt( std::string prompt ) {
	this->_prompt = prompt;
	return;
}

std::string Character::getPrompt() {
	return this->_prompt;
}

void Character::cSave() {
	std::string file = PFILE_DIR;
	file << lowerString( this->getName().c_str() ) << ".pfile";
	std::ofstream save( file.c_str() );
	if ( !save ) {
		log( ACCOUNT, file << " could not be opened for writing." );
		return;
	}
	this->Save( save, _room ); // Creature::Save()

	save << "\n// Character data...\n";
	save << _id << '\n';
	save << _pword << '\n';
	save << _prompt << '\n';
	save << _lname << '\n';
	save << _prof << '\n';
	save << _clan << '\n';

	save << _bankgold << ' ' << _banksilver << '\n';
	save << _mobdeaths << ' ' << _mobkills << ' ' << _pkdeaths << ' ' << _pkkills << '\n';
	save << _exp << ' ' << _tnl << '\n';
	save << _pracs << ' ' << _trains << ' ' << _gains << '\n';
	save << _on << '\n';
	save << _title << '\n';
	save << _eyedesc << ' ' << _eyecolor << '\n';
	save << _hairdesc << ' ' << _haircolor << '\n';
	save << _cheight << ' ' << _cweight << ' ' << _hand << '\n';
	save << _house << '\n';
	save << _points << ' ' << _echocolor << '\n';
	save << _poofin << '\n' << _poofout << '\n';

	save << "\n// Unsent notes...";
	for ( std::list< Note* >::iterator n_it = _notes.begin(); n_it != _notes.end(); n_it++ )
		(*n_it)->save( save );

	save << "\n\n// File written " << Timestamp::Instance().GetDateTime() << '\n';

	save.close();
    return;
}

int Character::cLoad() {
	char ctemp[2048];
	std::string file = PFILE_DIR;
	file << lowerString( this->getName().c_str() ) << ".pfile";

	std::ifstream load( file.c_str() );
	if ( !load ) {
		log( ACCOUNT, file << " could not be opened for reading." );
		return -1;
	}
	this->Load( load ); // Creature::Load()

	// Add this Character to the room which was loaded in the Creature::Load() call.
	getRoom()->Add( this );

	// Load the Character data in.
	load >> _id;
	load >> _pword;
	load.get(); load.getline( ctemp, 2048 ); _prompt = ctemp;
	load >> _lname >> _prof;
	load.get(); load.getline( ctemp, 2048 ); strcpy( _clan, ctemp );
	load >> _bankgold >> _banksilver >> _mobdeaths >> _mobkills >> _pkdeaths >> _pkkills >> _exp >> _tnl;
	load >> _pracs >> _trains >> _gains;
	load >> _on;
	load.get(); load.getline( ctemp, 2048 ); strcpy( _title, ctemp );
	load >> _eyedesc >> _eyecolor >> _hairdesc >> _haircolor >> _cheight >> _cweight >> _hand;
	load.get(); load.getline( ctemp, 2048 ); strcpy( _house, ctemp );
	load >> _points >> _echocolor;
	load.get(); load.getline( ctemp, 2048 ); _poofin = ctemp;
	load.getline( ctemp, 2048 ); _poofout = ctemp;

	// Load unsent notes...
	char ctmp[100000];
	while ( load.peek() != EOF ) {
		load.getline( ctmp, 100000 );
		if ( strcmp( ctmp, "**NOTE" ) == 0 ) {
			addNote()->load( load );
		}
	}

	load.close();
	return 0;
}

std::string Character::stringHand() {
	std::string buf;

	if ( _hand == RIGHT )
		buf = "right";
	else
		buf = "left";

	return buf;
}

std::list< Note* >& Character::getNotes() {
	return _notes;
}

Note* Character::addNote() {
	Note* note = new Note;
	getNotes().push_back( note );
	return note;
}

void Character::dropNote( Note* note ) {
	getNotes().remove( note );
	delete note;
	note = 0;
	return;
}

void Character::setNote( Note* note ) {
	_note = note;
	return;
}

Note* Character::getNote() {
	return _note;
}

void Character::setBoard( Board* board ) {
	_board = board;
	return;
}

Board* Character::getBoard() {
	return _board;
}

Area* Character::getArea() {
	return _area;
}

void Character::setArea( Area* area ) {
	_area = area;
	return;
}

bool Character::Create() {
	
	return true;
}

bool Character::Delete() {
	
	return true;
}

int Character::GetStatus( ) {
	return _status;
}

void Character::SetStatus( int status ) {
	_status = status;
}

void Character::Send( char * message, ... ) {
	va_list args;
	char buf[MAX_BUFFER];
	string buf2;

    va_start( args, message );

	vsprintf( buf, message, args);
	buf2 = _socket->GetOutput();
	buf2.append( buf );
	
	_socket->SetOutput( buf2 );
	va_end( args );
}

void Character::Send( const string &message ) {
	string buf;
	buf.append( message );	
	_socket->SetOutput( buf );
}

void Character::SetSocket( Socket* socket ) {
	_socket = socket;
}

Socket* Character::GetSocket( ) {
	return _socket;
}

void Character::SetGotInput( bool value ) {
	_gotInput = value;
}

bool Character::GotInput( ) {
	return _gotInput;
}

void Character::setCharacter( Character* character ) {
	_character = character;
}

Character* Character::getCharacter() {
	return _character;
}

void Character::FlushOutput( ) {
	string output;
	string buf;
	string buf2;
	string buf3;
	string colorClear;
	// This will add a prompt to the end of output
	// Ofcourse, one needs some text before it'll add a prompt
	// or we can add a prompt if we get some input and it calls for it. :)
	
	output = _socket->GetOutput();
	if ( output.empty() != true || _gotInput ) {
			
		
		//if ( this->waiting == false )  { // Don't send a prompt if there's delayed text going
			if ( !_gotInput ) {
					output.insert( 0, "\n\r" );
			} else {
				// Only if there's no input set gotInput to false
				// we do it like this so there isn't an extra newline
				// everytime you get some output
				if ( _socket->GetInput().empty() )
					_gotInput = false;
			}//*/
			//output.append( "\n\r" + _handlers.front()->Prompt( (this) ) );
			if ( _status == LOGIN )
				;
			else if ( _status == NEDIT ) {
				if ( _note == 0 )
					buf = "[no note selected]";
				else
					buf << "[note " << _note->getId() << ']';
			} else if ( _status == AEDIT ) {
				if ( _area == 0 )
					buf = "[no area selected]";
				else
					buf << "[area " << _area->GetKeyword() << ']';
			} else if ( _status == REDIT ) {
				buf << "[room " << _room->GetVnum() << ']';
			} else if ( _status == MEDIT ) {
				buf << "[mob " << _mob->getVnum() << ']';
			} else if ( _status == OEDIT ) {
				buf << "[object " << _object->getVnum() << ']';
			} else if ( _status == PEDIT ) {
				buf << "[player " << _character->getName() << ']';
			} else
				buf = formatPrompt();
			if ( _vedit )
				buf = "[symphony text editor]";
			if ( _status != LOGIN )
				output.append( "\n\r" + buf + "{x " );
			_socket->SetOutput( output );
			
		//}
	}

	// color parsing...
	std::string temp = _socket->GetOutput();
	for ( int x=0; x < (int)temp.size(); x++ ) {
		if ( temp[x] == '{' ) {
			buf3 << cprint_private( 'x' );
			if ( temp[x+1] == '!' || temp[x+1] == '@' ) {
				buf3 << cprint_private( temp[x+1], temp[x+2] );
				x += 2;
			}
			else {
				buf3 << cprint_private( temp[x+1] );
				x++;
			}
		}
		else
			buf3 << temp[x];
	}
	_socket->SetOutput( buf3 );
}

void Character::SetDisconnected( bool value ) {
	_disconnected = value;
	_socket->SetDisconnected( true );
}

bool Character::IsDisconnected( ) {
	return _disconnected;
}

// Public accessor methods and other shite...
int Character::GetConnection() {
	return _connection;
}

void Character::SetConnection( int connection ) {
	_connection = connection;
}

char* Character::GetPword( void ) {
	return _pword;
}

char Character::GetPword( int x ) {
	return _pword[x];
}

void Character::SetPword( char* val ) {
	strcpy( _pword, val );
	return;
}

void Character::SetPword( const char* val ) {
	strcpy( _pword, val );
	return;
}

void Character::SetPword( int x, char val ) {
	_pword[x] = val;
}

char* Character::GetLname( void )
{
	return _lname;
}

char Character::GetLname( int x )
{
	return _lname[x];
}

void Character::SetLname( char* val )
{
	strcpy( _lname, val );
	return;
}

void Character::SetLname( const char* val )
{
	strcpy( _lname, val );
	return;
}

void Character::SetLname( int x, char val )
{
	_lname[x] = val;
}

char* Character::GetProf( void )
{
	return _prof;
}

char Character::GetProf( int x ) {
	return _prof[x];
}

void Character::SetProf( char* val ) {
	strcpy( _prof, val );
	return;
}

void Character::SetProf( const char* val ) {
	strcpy( _prof, val );
	return;
}

void Character::SetProf( int x, char val ) {
	_prof[x] = val;
}

char* Character::GetClan( void ) {
	return _clan;
}

char Character::GetClan( int x ) {
	return _clan[x];
}

void Character::SetClan( char* val ) {
	strcpy( _clan, val );
	return;
}

void Character::SetClan( const char* val ) {
	strcpy( _clan, val );
	return;
}

void Character::SetClan( int x, char val ) {
	_clan[x] = val;
}

int Character::GetBankgold() {
	return _bankgold;
}

void Character::setMob( Mob* mob ) {
	_mob = mob;
	return;
}

Mob* Character::getMob() {
	return _mob;
}

void Character::setObject( Object* object ) {
	_object = object;
	return;
}

Object* Character::getObject() {
	return _object;
}

void Character::SetBankgold( int bankgold ) {
	_bankgold = bankgold;
	return;
}

int Character::getId() {
	return _id;
}

int Character::GetBanksilver() {
	return _banksilver;
}

void Character::SetBanksilver( int banksilver ) {
	_banksilver = banksilver;
	return;
}

int Character::GetMobdeaths()
{
	return _mobdeaths;
}

void Character::SetMobdeaths( int mobdeaths )
{
	_mobdeaths = mobdeaths;
}

int Character::GetMobkills()
{
	return _mobkills;
}

void Character::SetMobkills( int mobkills )
{
	_mobkills = mobkills;
}

int Character::GetPkdeaths()
{
	return _pkdeaths;
}

void Character::SetPkdeaths( int pkdeaths )
{
	_pkdeaths = pkdeaths;
}

int Character::GetPkkills()
{
	return _pkkills;
}

void Character::SetPkkills( int pkkills )
{
	_pkkills = pkkills;
}

int Character::GetExp()
{
	return _exp;
}

void Character::SetExp( int exp )
{
	_exp = exp;
}

int Character::GetTnl()
{
	return _tnl;
}

void Character::SetTnl( int tnl )
{
	_tnl = tnl;
}

int Character::GetPracs()
{
	return _pracs;
}

void Character::SetPracs( int pracs )
{
	_pracs = pracs;
}

int Character::GetTrains()
{
	return _trains;
}

void Character::SetTrains( int trains )
{
	_trains = trains;
}

int Character::GetGains()
{
	return _gains;
}

void Character::SetGains( int gains )
{
	_gains = gains;
}

bool Character::GetOn() {
	return _on;
}

void Character::SetOn( bool on ) {
	_on = on;
}

char* Character::GetTitle( void )
{
	return _title;
}

char Character::GetTitle( int x )
{
	return _title[x];
}

void Character::SetTitle( char* val )
{
	strcpy( _title, val );
	return;
}

void Character::SetTitle( const char* val )
{
	strcpy( _title, val );
	return;
}

void Character::SetTitle( int x, char val )
{
	_title[x] = val;
}

char* Character::GetEyedesc( void )
{
	return _eyedesc;
}

char Character::GetEyedesc( int x )
{
	return _eyedesc[x];
}

void Character::SetEyedesc( char* val )
{
	strcpy( _eyedesc, val );
	return;
}

void Character::SetEyedesc( const char* val )
{
	strcpy( _eyedesc, val );
	return;
}

void Character::SetEyedesc( int x, char val )
{
	_eyedesc[x] = val;
}

char* Character::GetEyecolor( void )
{
	return _eyecolor;
}

char Character::GetEyecolor( int x )
{
	return _eyecolor[x];
}

void Character::SetEyecolor( char* val )
{
	strcpy( _eyecolor, val );
	return;
}

void Character::SetEyecolor( const char* val )
{
	strcpy( _eyecolor, val );
	return;
}

void Character::SetEyecolor( int x, char val )
{
	_eyecolor[x] = val;
}

char* Character::GetHairdesc( void )
{
	return _hairdesc;
}

char Character::GetHairdesc( int x )
{
	return _hairdesc[x];
}

void Character::SetHairdesc( char* val )
{
	strcpy( _hairdesc, val );
	return;
}

void Character::SetHairdesc( const char* val )
{
	strcpy( _hairdesc, val );
	return;
}

void Character::SetHairdesc( int x, char val )
{
	_hairdesc[x] = val;
}

char* Character::GetHaircolor( void )
{
	return _haircolor;
}

char Character::GetHaircolor( int x )
{
	return _haircolor[x];
}

void Character::SetHaircolor( char* val )
{
	strcpy( _haircolor, val );
	return;
}

void Character::SetHaircolor( const char* val )
{
	strcpy( _haircolor, val );
	return;
}

void Character::SetHaircolor( int x, char val )
{
	_haircolor[x] = val;
}

char* Character::GetCheight( void )
{
	return _cheight;
}

char Character::GetCheight( int x )
{
	return _cheight[x];
}

void Character::SetCheight( char* val )
{
	strcpy( _cheight, val );
	return;
}

void Character::SetCheight( const char* val )
{
	strcpy( _cheight, val );
	return;
}

void Character::SetCheight( int x, char val )
{
	_cheight[x] = val;
}

char* Character::GetCweight( void )
{
	return _cweight;
}

char Character::GetCweight( int x )
{
	return _cweight[x];
}

void Character::SetCweight( char* val )
{
	strcpy( _cweight, val );
	return;
}

void Character::SetCweight( const char* val )
{
	strcpy( _cweight, val );
	return;
}

void Character::SetCweight( int x, char val )
{
	_cweight[x] = val;
}

int Character::GetHand()
{
	return _hand;
}

void Character::SetHand( int hand )
{
	_hand = hand;
}

char* Character::GetHouse( void )
{
	return _house;
}

char Character::GetHouse( int x )
{
	return _house[x];
}

void Character::SetHouse( char* val )
{
	strcpy( _house, val );
	return;
}

void Character::SetHouse( const char* val )
{
	strcpy( _house, val );
	return;
}

void Character::SetHouse( int x, char val )
{
	_house[x] = val;
}

int Character::GetPoints()
{
	return _points;
}

void Character::SetPoints( int points )
{
	_points = points;
}

char Character::GetEchocolor() {
	return _echocolor;
}

void Character::SetEchocolor( char echocolor ) {
	_echocolor = echocolor;
	return;
}

std::string& Character::getPoofin() {
	return _poofin;
}

void Character::setPoofin( std::string& poofin ) {
	_poofin = poofin;
	return;
}

std::string& Character::getPoofout() {
	return _poofout;
}

void Character::setPoofout( std::string& poofout ) {
	_poofout = poofout;
	return;
}

// Other methods...
std::string Character::promptSwitch( char c ) {
	std::string replaced;

	switch ( c ) {
		case 'h': ; replaced << _hp; break;
		case 'H': ; replaced << _mhp; break;
		case 'm': ; replaced << _mana; break;
		case 'M': ; replaced << _mmana; break;
		case 'v': ; replaced << _move; break;
		case 'V': ; replaced << _mmove; break;
		case 'g': ; replaced << _goldheld; break;
		case 'G': ; replaced << _bankgold; break;
		case 's': ; replaced << _silverheld; break;
		case 'S': ; replaced << _banksilver; break;
		case 'r': ; replaced << _room->GetVnum(); break;
		default: replaced << '%'; break;
	}

	return replaced;
}

std::string Character::formatPrompt() {
	std::string unformatted = _prompt;
	std::string formatted;

	for ( int x=0; x < (int)unformatted.size(); x++ ) {
		if ( unformatted[x] == '%' ) {
			formatted << Character::promptSwitch( unformatted[x+1] );
			x++;
		}
		else
			formatted << unformatted[x];
	}

	return formatted;
}
